#include <unistd.h>
#include <cstring>
#include <fstream>
#include <iostream>

#include "aiui/AIUI_V2.h"
#include "aiui/PcmPlayer_C.h"
#include "json/json.h"
#include "StreamNlpTtsHelper.h"
#include "IatResultUtil.h"
#include "Base64Util.h"
#include <sys/socket.h>
#include <net/if.h>
#include <sys/ioctl.h>

#define AIUI_SLEEP(x) usleep(x * 1000)
// 使用的AIUI服务版本：1（语义技能），2（语义技能 + 大模型），3（语义技能 + 大模型 + 极速交互）
#define AIUI_VER 3

#if AIUI_VER == 3
    // 是否使用语义后合成。当在AIUI平台应用配置页面打开"语音合成"开关时，需要打开该宏
    #define USE_POST_SEMANTIC_TTS 1
#endif

#define TEST_ROOT_DIR "./REIAIUI/"
#define CFG_FILE_PATH "./REIAIUI/cfg/aiui.cfg"
#define TEST_AUDIO_PATH "./REIAIUI/audio/test.pcm"
#define LOG_DIR         "./REIAIUI/log/"
#define MSC_DIR         "./REIAIUI/msc/"
#define TEST_TTS_PATH   "./REIAIUI/text/tts.txt"
#define TEST_SEE_SAY_PATH "./REIAIUI/text/see_say.txt"
#define VOICE_CLONE_AUDIO_PATH "./REIAIUI/audio/voice_clone_1ch24K16bit.pcm"
#define VOICE_CLONE_RES_ID_PATH "./voice_clone_reg_id.txt"
#define WAKE_WORD_TEXT_PATH "./REIAIUI/text/wakeup_wake.txt"

using namespace std;
using namespace aiui_va;
using namespace aiui_v2;

class REIListener : public IAIUIListener
{
private:
    class TtsHelperListener : public StreamNlpTtsHelper::Listener
    {
    public:
        void onText(const StreamNlpTtsHelper::OutTextSeg& textSeg) override;
        void onFinish(const string& fullText) override;
        void onTtsData(const Json::Value& bizParamJson, const char* audio, int len) override;

    };
    
    int mStreamTtsIndex{0};
    static void processIntentJson(Json::Value& params,
                           Json::Value& intentJson,
                           std::string& resultStr,
                           int eosRsltTime,
                           std::string& sid);
    void handleEvent(const IAIUIEvent& event);
    fstream mFs;
    string mCurTtsSid;// 当前合成sid
    string mCurIatSid;// 当前识别sid
    string mIatTextBuffer;// 识别结果缓存
    string mStreamNlpAnswerBuffer;// 流式nlp的应答语缓存
    int mTtsLen = 0;// 当前收到了tts音频的长度
    int mIntentCnt = 0;// 意图的数量
    std::shared_ptr<StreamNlpTtsHelper> m_pTtsHelper;
public:
    bool mMoreDetails = true;// 是否输出更多信息
    REIListener();
    ~REIListener(){aiui_pcm_player_destroy();}// 析构时销毁播放器，释放资源
    //重写onEvent方法，SDK通过回调该方法抛出各种事件，在这里针对事件做对应的处理。
    void onEvent(const IAIUIEvent& event) override; 
};

string readFileAsString(const string& path);
void createAgent(bool more, const char* cfgPath); //创建一个AIUI
void destroyAgent(); //关闭一个AIUI
void wakeup(); //唤醒服务
void resetWakeup(); //重新唤醒
void stop(); //停止AIUI服务
void start(); //开启AIUI服务
void resetAIUI(); //重启AIUI服务
void writeAudioFromLocal(bool repeat);
void startRecordAudio(); //开始录音
void stopRecordAudio(); //结束录音
void writeText(const string& text, bool needWakeup = true); //文本写入aiui
int startTTS(const string& text, const string& tag); //开始语音合成
int startTTS(const string& text, int dts, const string& tag); 
void syncSchemaData(int type = AIUIConstant::SYNC_DATA_SCHEMA); //同步动态实体